package model.persistence;

import java.sql.Connection;
import java.sql.SQLException;



public abstract class AbstractTransactionManager implements TransactionManager{

    private String database;
    private String username;
    private String password;

    protected Connection connection;

    private boolean connected = false;

    public AbstractTransactionManager(String username, String password, String database){
       this.setUsername(username);
       this.setPassword(password);
       this.setDatabase(database);
       this.setConnection(null);
    }

    

    protected String getDatabase() {
        return database;
    }

    protected void setDatabase(String database) {
        this.database = database;
    }

    protected String getUsername() {
        return username;
    }

    protected void setUsername(String username) {
        this.username = username;
    }

    protected String getPassword() {
        return password;
    }

    protected void setPassword(String password) {
        this.password = password;
    }

    protected Connection getConnection() {
        return connection;
    }

    protected void setConnection(Connection connection) {
        this.connection = connection;
    }

    //template
    protected abstract Connection createConnection() throws ClassNotFoundException, SQLException; //SERA IMPLEMENTADO NAS SUB-CLASSES

    @Override
    public void connect() throws ClassNotFoundException, SQLException{
        this.connection = this.createConnection();        
        this.connected = true;
        this.connection.setAutoCommit(false);
    }

    @Override
    public void disconnect() throws SQLException{
        if(this.connection == null)
            throw new SQLException("Não existe conexão com banco de dados.");
        this.connection.close();
        this.connected = false;

    }

    @Override
    public boolean isConnected(){
        return this.connected;        
    }

    @Override
    public void commit() throws SQLException{
        if(this.connection == null)
            throw new SQLException("Não existe conexão com banco de dados.");
        this.connection.commit();
    }

    @Override
    public void rollback() throws SQLException{
        if(this.connection == null)
            throw new SQLException("Não existe conexão com banco de dados.");
        this.connection.rollback();
    }

    //template - complete a lacuna - classe concreta
    protected abstract DAO createDAO(String entity)  throws ClassNotFoundException, IllegalAccessException, InstantiationException, CloneNotSupportedException;

    public Object insert(String entity, Object dto) throws SQLException{
        DAO dao = null;
        try{
        dao = this.createDAO(entity);
        }catch(Exception erro){
            throw new SQLException("Não foi possível inserir. \n Motivo: " + erro.getMessage());
        }
        dao.setConnection(this.connection);
        return dao.insert(dto);
    }

    public Object update(String entity, Object dto) throws SQLException{
        DAO dao = null;
        try{
            dao = this.createDAO(entity);
        }catch(Exception erro){
            throw new SQLException("Não foi possível atualizar. \n Motivo: " + erro.getMessage());
        }
        dao.setConnection(this.connection);
        return dao.update(dto);
    }

    public void delete(String entity, Object dto) throws SQLException{
        DAO dao = null;
        try{
            dao = this.createDAO(entity);
        }catch(Exception erro){
            throw new SQLException("Não foi possível apagar. \n Motivo: " + erro.getMessage());
        }
        dao.setConnection(this.connection);
        dao.delete(dto);
    }

    public Object find(String entity, Object oid) throws SQLException{
        DAO dao = null;
        try{
            dao = this.createDAO(entity);
        }catch(Exception erro){
            throw new SQLException("Não foi possível localizar. \n Motivo: " + erro.getMessage());
        }
        dao.setConnection(this.connection);
        return dao.find(oid);
    }

    @Override
    public DAO getDAO(String entity) throws CloneNotSupportedException, InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
        DAO dao = this.createDAO(entity);
        dao.setConnection(this.connection);
        return dao;
    }
}
